from datetime import datetime
from typing import List

from config.logging import logger

from elasticsearch.helpers import bulk
from sqlalchemy import select
from sqlalchemy.orm import Session

from config.elastic import es, BLOG_INDEX
from models.blog import Blog, BlogCategory, BlogContent
from schemas.blog_elastic import BlogElastic, BlogSearch


def sync_all_blog(db: Session) -> bool:
    query = select(
        Blog.id,
        Blog.title,
        BlogCategory.name.label("category"),
        BlogContent.content.label("content"),
        Blog.create_time.label("createTime"),
        Blog.update_time.label("updateTime"),
    ).select_from(Blog).outerjoin(
        BlogCategory, Blog.category_id == BlogCategory.id
    ).outerjoin(
        BlogContent, Blog.content_id == BlogContent.id
    )
    results = db.execute(query).fetchall()

    actions = [
        {
            "_op_type": "index",  # 如果存在则更新，不存在则创建
            "_index": BLOG_INDEX,
            "_id": blog.id,
            "_source": {
                "title": blog.title,
                "category": blog.category,
                "content": blog.content.decode("utf-8"),
                "createTime": blog.createTime.strftime("%Y-%m-%d %H:%M:%S"),
                "updateTime": blog.updateTime.strftime("%Y-%m-%d %H:%M:%S")
            }
        }
        for blog in results
    ]

    success_count, errors = bulk(es, actions=actions)

    if errors:
        logger.error(f"部分文档同步失败，成功同步 {success_count} 条")
        return False

    logger.info(f"成功同步 {success_count} 条博客到 Elasticsearch")
    return True


def add_blog_elastic(blog: BlogElastic) -> bool:
    now = datetime.now()
    blog.createTime = now.strftime("%Y-%m-%d %H:%M:%S")
    blog.updateTime = now.strftime("%Y-%m-%d %H:%M:%S")

    es.index(
        index=BLOG_INDEX,
        id=blog.id,
        body=blog.model_dump()
    )

    return True


def update_blog_elastic(blog: BlogElastic) -> bool:
    now = datetime.now()
    blog.updateTime = now.strftime("%Y-%m-%d %H:%M:%S")

    es.index(
        index=BLOG_INDEX,
        id=blog.id,
        body=blog.model_dump()
    )

    return True


def delete_blog(blog_id: int) -> bool:
    es.delete(index=BLOG_INDEX, id=blog_id)

    return True


def search_blog(keyword: str) -> List[BlogSearch]:
    # 构造查询请求
    body = {
        "query": {
            "multi_match": {
                "query": keyword,
                "fields": ["title^3", "content"],
                "type": "phrase"
            }
        },
        "highlight": {
            "pre_tags": ["<mark>"],
            "post_tags": ["</mark>"],
            "fields": {
                "title": {},
                "content": {
                    "fragment_size": 150,
                    "number_of_fragments": 2,
                    "no_match_size": 100
                }
            }
        },
        "_source": ["title", "content"]
    }

    response = es.search(index=BLOG_INDEX, body=body)

    results = []
    for hit in response["hits"]["hits"]:
        highlight = hit.get("highlight", {})

        # 合并所有高亮片段（标题+内容）
        all_highlights = []
        if "title" in highlight:
            all_highlights.extend(highlight["title"])
        if "content" in highlight:
            all_highlights.extend(highlight["content"])

        # 优先使用高亮内容，否则截取内容开头
        displayed_content = " ".join(all_highlights) if all_highlights \
            else hit["_source"].get("content", "")[:200] + "..."

        results.append(BlogSearch(
            id=hit["_id"],
            title=hit["_source"]["title"],
            content=displayed_content,
            highlight=" | ".join(all_highlights)  # 合并所有高亮片段
        ))

    return results
